# -*- coding: utf-8 -*-
"""
@Time ： 2023/10/17 1:42
@Auth ： y.h
@File ：numpy_calculation.py
@IDE ：PyCharm
@Motto：The sooner you start to code, the longer the program will take. —— Roy Carlson
"""
import numpy
import pandas

from pythonProjectTemplate.Controller.configurator_controller import 配置器
from pythonProjectTemplate.Controller.pandas_query_controller import pandas数据筛查
from pythonProjectTemplate.Entity.SystemEntity.many_col_iter_calculation_properties import 多列多行迭代运算配置文件
from pythonProjectTemplate.Entity.SystemEntity.many_row_and_row_calculation_properties import 多行与多行迭代运算配置文件
from pythonProjectTemplate.Entity.SystemEntity.single_valued_matrix_calculation_properties import 单值矩阵运算配置文件


def pandas_numpy_conversion(data_arr):
    if type(data_arr) == type(pandas.DataFrame()):
        return numpy.array(data_arr)
    elif type(data_arr) == type(numpy.array(1)):
        return pandas.DataFrame(data_arr)
    else:
        print("参数类型错误,请检查!")


def many_col_row_iter_calculation(properties: 多列多行迭代运算配置文件):
    df_1 = properties.get_df_1()
    df_2 = properties.get_df_2()
    数据截取配置文件_1 = 配置器().数据裁切配置()
    数据截取配置文件_2 = 配置器().数据裁切配置()
    if type(df_1) == type(pandas.DataFrame()) and type(df_2) == type(pandas.DataFrame()):

        # 数据裁剪 ----->>>>>>>>>>>  开始
        if properties.get_col_end_1() > 0:
            # 获取指定列表内指定索引的值配置 ---->>>>>>>>>>>>>>  开始
            col_list = []
            for i in range(properties.get_col_begin_1(), properties.get_col_end_1()):
                col_list.append(i)

            数据截取配置文件_1.配置列索引(col_list)
            if properties.get_row_end_1() > 0:
                row_list = []
                for j in range(properties.get_row_begin_1(), properties.get_row_end_1()):
                    row_list.append(j)

                数据截取配置文件_1.配置行索引(row_list)

        elif len(properties.get_col_list_1()) > 0:
            数据截取配置文件_1.配置列索引(properties.get_col_list_1())
            if len(properties.get_row_list_1()) > 0:
                数据截取配置文件_1.配置行索引(properties.get_row_list_1())

        if properties.get_col_end_2() > 0:
            # 获取指定列表内指定索引的值配置 ---->>>>>>>>>>>>>>  开始
            col_list = []
            for i in range(properties.get_col_begin_2(), properties.get_col_end_2()):
                col_list.append(i)

            数据截取配置文件_2.配置列索引(col_list)
            if properties.get_row_end_2() > 0:
                row_list = []
                for j in range(properties.get_row_begin_2(), properties.get_row_end_2()):
                    row_list.append(j)

                数据截取配置文件_2.配置行索引(row_list)
            # 数据截取后文件 = pandas数据筛查.数据截取(df, 数据截取配置文件)
        elif len(properties.get_col_list_2()) > 0:
            数据截取配置文件_2.配置列索引(properties.get_col_list_2())

            if len(properties.get_row_list_2()) > 0:
                数据截取配置文件_2.配置行索引(properties.get_row_list_2())

            # 获取指定列表内指定索引的值配置 ---->>>>>>>>>>>>>>  结束

        # 数据裁剪 ----->>>>>>>>>>>  结束

        # 向量化运算  ------- >>>>>>>>>>  开始
        np_1 = pandas_numpy_conversion(pandas数据筛查().数据截取(df_1, 数据截取配置文件_1))

        np_2 = pandas_numpy_conversion(pandas数据筛查().数据截取(df_2, 数据截取配置文件_2))
        result = []
        df_result = []
        if properties.get_operator() is None:
            print("运算符未配置!")
            exit(True)
        else:
            try:
                operator = properties.get_operator()
                cal = None
                # 这里不这么写会报错!!!
                # todo 偷个懒就不抽象这个代码段了
                if operator.value == "add":
                    if properties.get_return_table_style():
                        for x in numpy.nditer(np_2, flags=["refs_ok"]):
                            result.append(x + np_1)
                    else:
                        for x in numpy.nditer(np_1, flags=["refs_ok"]):
                            result.append(x + np_2)
                elif operator.value == "subtract":
                    if properties.get_return_table_style():
                        for x in numpy.nditer(np_2, flags=["refs_ok"]):
                            result.append(x - np_1)
                    else:
                        for x in numpy.nditer(np_1, flags=["refs_ok"]):
                            result.append(x - np_2)
                elif operator.value == "multiply":
                    if properties.get_return_table_style():
                        for x in numpy.nditer(np_2, flags=["refs_ok"]):
                            result.append(x * np_1)
                    else:
                        for x in numpy.nditer(np_1, flags=["refs_ok"]):
                            result.append(x * np_2)
                elif operator.value == "Dividing":
                    if properties.get_return_table_style():
                        for x in numpy.nditer(np_2, flags=["refs_ok"]):
                            result.append(x / np_1)
                    else:
                        for x in numpy.nditer(np_1, flags=["refs_ok"]):
                            result.append(x / np_2)
                elif operator.value == "remainder":
                    cal = "%"

                result = numpy.array(result)
                for re in result:
                    df_result.append(pandas.DataFrame(re))

                return df_result

            except numpy.core._exceptions._ArrayMemoryError as e:
                print("内存溢出,请分割数据后计算!")
                exit(True)

        # 向量化运算  ------- >>>>>>>>>>  开始

    else:
        print("数据参数错误!")
        exit(True)


def many_row_and_row_iter_calculation(properties: 多行与多行迭代运算配置文件):
    df_1 = properties.get_df_1()
    df_2 = properties.get_df_2()

    if type(df_1) == type(pandas.DataFrame()) and type(df_2) == type(pandas.DataFrame()):
        # 数据截取 ------>>>>>  开始
        if (properties.get_col_index_1() < 0
                and properties.get_col_index_2() < 0
                and properties.get_row_begin_index_1() < 0
                and properties.get_row_end_index_1() < 0
                and properties.get_row_begin_index_2() < 0
                and properties.get_row_end_index_2() < 0):
            print("数据参数错误!")
            exit(True)
        else:
            if ((properties.get_row_end_index_1() - properties.get_row_begin_index_1() < 1)
                    and (properties.get_row_end_index_2() - properties.get_row_begin_index_2() < 1)):
                print("数据参数错误!")
                exit(True)
            else:
                index_list_1 = []
                index_list_2 = []
                for i_1 in range(properties.get_row_begin_index_1(), properties.get_row_end_index_1()):
                    index_list_1.append(i_1)
                for i_2 in range(properties.get_row_begin_index_2(), properties.get_row_end_index_2()):
                    index_list_2.append(i_2)

                数据截取配置文件_1 = (配置器().数据裁切配置()
                                      .配置列索引(properties.get_col_index_1())
                                      .配置行索引(index_list_1))
                数据截取配置文件_2 = (配置器().数据裁切配置()
                                      .配置列索引(properties.get_col_index_2())
                                      .配置行索引(index_list_2))

                np_1 = pandas_numpy_conversion(pandas数据筛查().数据截取(df_1, 数据截取配置文件_1))

                np_2 = pandas_numpy_conversion(pandas数据筛查().数据截取(df_2, 数据截取配置文件_2))
                # 数据截取 ------>>>>>  结束

                # 数据计算 ------>>>>>>   开始
                operator = properties.get_operator()
                # 这里不这么写会报错!!!
                result = []
                df_result = []
                if operator.value == "add":
                    if properties.get_return_table_style():
                        for x in numpy.nditer(np_2, flags=["refs_ok"]):
                            result.append(x + np_1)
                    else:
                        for x in numpy.nditer(np_1, flags=["refs_ok"]):
                            result.append(x + np_2)
                elif operator.value == "subtract":
                    if properties.get_return_table_style():
                        for x in numpy.nditer(np_2, flags=["refs_ok"]):
                            result.append(x - np_1)
                    else:
                        for x in numpy.nditer(np_1, flags=["refs_ok"]):
                            result.append(x - np_2)
                elif operator.value == "multiply":
                    if properties.get_return_table_style():
                        for x in numpy.nditer(np_2, flags=["refs_ok"]):
                            result.append(x * np_1)
                    else:
                        for x in numpy.nditer(np_1, flags=["refs_ok"]):
                            result.append(x * np_2)
                elif operator.value == "Dividing":
                    if properties.get_return_table_style():
                        for x in numpy.nditer(np_2, flags=["refs_ok"]):
                            result.append(x / np_1)
                    else:
                        for x in numpy.nditer(np_1, flags=["refs_ok"]):
                            result.append(x / np_2)
                elif operator.value == "remainder":
                    cal = "%"

                result = numpy.array(result)
                for re in result:
                    df_result.append(pandas.DataFrame(re))

                return df_result
    # 数据计算 ------>>>>>>   结束

    else:
        print("数据参数错误!")
        exit(True)


def single_valued_matrix_calculation(properties: 单值矩阵运算配置文件):
    df = properties.get_df()
    value = properties.get_value()

    if type(df) != type(pandas.DataFrame()):
        print("数据参数错误!")
        exit(True)
    elif properties.get_col_index() < 0 and properties.get_row_begin_index() < 0 and properties.get_row_end_index() < 0:
        print("参数错误!")
        exit(True)
    elif properties.get_row_end_index() - properties.get_row_begin_index() < 1:
        print("参数错误!")
        exit(True)
    else:
        # 数据截取 --->>>>>>>  开始
        index_list_1 = []

        for i_1 in range(properties.get_row_begin_index(), properties.get_row_end_index()):
            index_list_1.append(i_1)

        数据截取配置文件_1 = (配置器().数据裁切配置()
                              .配置列索引(properties.get_col_index())
                              .配置行索引(index_list_1))

        np_1 = pandas_numpy_conversion(pandas数据筛查().数据截取(df, 数据截取配置文件_1))
        # 数据截取 --->>>>>>>  结束

        # 数据计算 ------>>>>>>   开始
        operator = properties.get_operator()
        # 这里不这么写会报错!!!
        result = []
        df_result = []
        if operator.value == "add":
            if properties.get_is_value_calculation_table():
                for x in numpy.nditer(np_1, flags=["refs_ok"]):
                    result.append(value + x)
            else:
                for x in numpy.nditer(np_1, flags=["refs_ok"]):
                    result.append(x + value)
        elif operator.value == "subtract":
            if properties.get_is_value_calculation_table():
                for x in numpy.nditer(np_1, flags=["refs_ok"]):
                    result.append(value - x)
            else:
                for x in numpy.nditer(np_1, flags=["refs_ok"]):
                    result.append(x - value)
        elif operator.value == "multiply":
            if properties.get_is_value_calculation_table():
                for x in numpy.nditer(np_1, flags=["refs_ok"]):
                    result.append(value * x)
            else:
                for x in numpy.nditer(np_1, flags=["refs_ok"]):
                    result.append(x * value)
        elif operator.value == "Dividing":
            if properties.get_is_value_calculation_table():
                for x in numpy.nditer(np_1, flags=["refs_ok"]):
                    result.append(value / x)
            else:
                for x in numpy.nditer(np_1, flags=["refs_ok"]):
                    result.append(x / value)
        elif operator.value == "remainder":
            cal = "%"

        result = numpy.array(result)

        return pandas.DataFrame(result)
    # 数据计算 ------>>>>>>   结束
